﻿////////////////////////////////////////////////////////////
//
// From "Wireframe without Z-Fighting" article for XNA 2.0
// from Catalin's XNA blog (www.catalinzima.com)
//
// Ported to XNA 4.0 by Hristo Hristov
// Date: 21.09.11
//
// Revision 1
////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content;
using NOVA.Scenery;

namespace NOVA.Utilities
{
    /// <summary>
    /// This renders a given model as wireframe
    /// </summary>
    public class WireframeRenderer
    {
        /// <summary>
        /// Effect used to draw the wireframe
        /// </summary>
        BasicEffect wireframeEffect;
        GraphicsDevice m_graphicsDevice;

        private float depthBias = -0.000001f;

        /// <summary>
        /// DepthBias that should be applied when drawing the Wireframe
        /// </summary>
        public float DepthBias
        {
            get { return depthBias; }
            set { depthBias = value; }
        }
        
        private Color wireColor = Color.Gold;

        /// <summary>
        /// Color of the Wireframe
        /// </summary>
        public Color WireframeColor
        {
            get { return wireColor; }
            set { wireColor = value; }
        }

        public WireframeRenderer(GraphicsDevice graphicsDevice)
        {
            wireframeEffect = new BasicEffect(graphicsDevice);
            wireframeEffect.DiffuseColor = wireColor.ToVector3();

            m_graphicsDevice = graphicsDevice;
        }

        /// <summary>
        /// Draw a model in wireframe mode.
        /// Will use DepthBias, to avoid Z-Fighting
        /// </summary>
        /// <param name="world">The World Matrix</param>
        /// <param name="view">The View Matrix</param>
        /// <param name="projection">The Projection Matrix</param>
        public void DrawWireframe(RenderHandler renderDelegate, Matrix world, Matrix view, Matrix projection)
        {
            RasterizerState oldRasterizer = m_graphicsDevice.RasterizerState;

            RasterizerState newRasterizer = new RasterizerState();

            // Set fillmode to wireframe
            newRasterizer.FillMode = FillMode.WireFrame;

            // Set the DepthBias to avoid an overlapping 
            // between model and wireframe
            newRasterizer.DepthBias = depthBias;

            m_graphicsDevice.RasterizerState = newRasterizer;
            
            wireframeEffect.World = world;
            wireframeEffect.View = view;
            wireframeEffect.Projection = projection;

            wireframeEffect.CurrentTechnique.Passes[0].Apply();

            // Draw model using out custom effect
            renderDelegate();

            // Restore FillMode to Solid and depthBias
            m_graphicsDevice.RasterizerState = oldRasterizer;
        }
    }
}